// -*-c++-*- Copyright (C) 2011 osgPango Development Team
// $Id$

#ifndef OSGPANGO_GLYPHRENDERER
#define OSGPANGO_GLYPHRENDERER

#include <osg/Geometry>
#include <osg/Texture2D>
#include <osgCairo/Image>
#include <osgPango/Export>
#include <osgPango/GlyphLayer>

namespace osgPango {

// This object packages up all the state stuff we need to shimmy around.
struct OSGPANGO_EXPORT GlyphGeometryState {
	std::vector<osg::Texture*> textures;
	std::vector<osg::Vec3>     colors;
};

typedef std::pair<osg::Geometry*, GlyphGeometryState> GeometryAndState;
typedef std::list<GeometryAndState>                   GeometryList;

class OSGPANGO_EXPORT GlyphRenderer: public osg::Referenced {
public:
	GlyphRenderer();

	// This method returns an osg::Vec4 object whose values correspond to the following:
	// the x origin offset, y origin offset, extra width, and extra height respectively.
	// It is used when custom "effects" implementations needs to inform the cache object
	// that additional space should be required for proper positioning.
	virtual osg::Vec4 getExtraGlyphExtents() const;
	
	virtual bool renderLayer(
		unsigned int,
		cairo_t*,
		cairo_glyph_t*,
		unsigned int,
		unsigned int
	);
	
	virtual bool updateOrCreateState (int pass, osg::Geode*);
	virtual bool updateOrCreateState (osg::Geometry*, const GlyphGeometryState&);

	// You can override this method to enable mipmapping, if you like.
	virtual osg::Texture2D* createTexture(osg::Image*);

	void setName(const std::string& name) {
		_name = name;
	}

	void setPixelSpacing(unsigned int spacing) {
		_pixelSpacing = spacing;
	}

	void setMinFilterMode(osg::Texture::FilterMode fm) {
		_minFilter = fm;
	}

	const std::string& getName() const {
		return _name;
	}

	unsigned int getPixelSpacing() const {
		return _pixelSpacing;
	}

	osg::Texture::FilterMode getMinFilterMode() const {
		return _minFilter;
	}

	void addLayer     (GlyphLayer*);
	void removeLayer  (unsigned int);
	void replaceLayer (unsigned int, GlyphLayer*);
	void clearLayers  ();

	virtual unsigned int getNumLayers() const {
		return _layers.size();
	}

	virtual unsigned int getNumPasses() const { 
		return 1;
	}

	virtual cairo_format_t getImageFormatForLayer(unsigned int);

protected:
	bool _setFragmentShader (osg::Geode*, const std::string&);

	std::string                            _name;
	std::vector<osg::ref_ptr<GlyphLayer> > _layers;
	unsigned int                           _pixelSpacing;
	osg::Texture::FilterMode               _minFilter;
};

class OSGPANGO_EXPORT GlyphRendererDefault: public GlyphRenderer {
public:
	GlyphRendererDefault();
	
	virtual bool updateOrCreateState(int pass, osg::Geode*);
};

class OSGPANGO_EXPORT GlyphRendererOutline: public GlyphRenderer {
public:
	GlyphRendererOutline(unsigned int = 2);

	virtual bool updateOrCreateState(int pass, osg::Geode*);
};

class OSGPANGO_EXPORT GlyphRendererShadow: public GlyphRenderer {
public:
	GlyphRendererShadow(int = 1, int = 1);

	virtual bool updateOrCreateState(int pass, osg::Geode*);
};

class OSGPANGO_EXPORT GlyphRendererShadowBlur: public GlyphRenderer {
public:
	GlyphRendererShadowBlur(int = 0, int = 0, unsigned int = 2, unsigned int = 0);
	
	virtual bool updateOrCreateState(int pass, osg::Geode*);
};

class OSGPANGO_EXPORT GlyphRendererShadowInset: public GlyphRenderer {
public:
	GlyphRendererShadowInset(int = 0, int = 0, unsigned int = 2, unsigned int = 0);
	
	virtual bool updateOrCreateState(int pass, osg::Geode*);
};

}

#endif
